#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"
#include <future>
#include <functional>

// 客户端的Requestor类就像是一个"请求发送器"，负责：
// 1.发送请求到服务器-send()
// 2.等待或处理服务器的响应-onResponse()
// 3.提供三种不同的使用方式：
// 同步方式（发送请求后等待结果）
// 异步方式（发送请求后可以做其他事，稍后再检查结果）
// 回调方式（发送请求后继续做其他事，当结果到达时自动调用指定的函数）



namespace bitrpc{
    namespace client{
        // Requestor类：客户端请求发送器，管理RPC请求的发送和响应处理
        // 支持两种请求模式：异步请求和回调式请求
        class Requestor{
            public:
                using ptr = std::shared_ptr<Requestor>;
                using RequestCallback = std::function<void(const BaseMessage::ptr&)>;   // 回调函数类型定义，用于处理异步响应
                using AsynResponse = std::future<BaseMessage::ptr>;                     // 异步响应类型，基于C++11 future机制

                // 请求描述结构：记录一个RPC请求的所有相关信息
                struct RequestDescribe{
                    using ptr = std::shared_ptr<RequestDescribe>;

                    BaseMessage::ptr request;                   // 原始请求消息
                    RType rtype;                                // 请求类型（异步/回调）
                    std::promise<BaseMessage::ptr> response;    // Promise对象，用于设置异步结果
                    RequestCallback callback;                   // 回调函数，用于回调模式
                };
                
//////////////////////// 响应处理函数：当收到服务端响应时调用

//扩展性考虑：const BaseConnection::ptr &conn
                void onResponse(const BaseConnection::ptr &conn, BaseMessage::ptr &msg){
                    std::string rid = msg->rid();
                    RequestDescribe::ptr rdp = getDescribe(rid);    // 根据请求ID查找对应的请求描述
                    if(rdp.get() == nullptr){
                        ELOG("收到响应 - %s, 但是未找到对应的请求描述!", rid.c_str());
                        return;
                    }
                    
                    // 根据请求类型分别处理响应
                    if(rdp->rtype == RType::REQ_ASYNC){
                        rdp->response.set_value(msg);               // 异步模式：设置promise值，解除future的阻塞
                    }else if(rdp->rtype == RType::REQ_CALLBACK){
                        if(rdp->callback) rdp->callback(msg);       // 回调模式：调用用户提供的回调函数
                    }else{
                        ELOG("请求类型未知!");
                    }
                    delDescribe(rid);   // 请求处理完成，清理资源
                }
/////////////////////////////////////////////////////发送信息

                // 异步请求发送：返回future对象，可以稍后获取结果
                bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, AsynResponse &async_rsp){
                    RequestDescribe::ptr rdp = newDescribe(req, RType::REQ_ASYNC);
                    if(rdp.get() == nullptr){
                        ELOG("构造请求描述对象失败!");
                        return false;
                    }
                    conn->send(req);                        // 通过BaseConnection父类底层网络库，连接发送请求
                    async_rsp = rdp->response.get_future(); // 获取future对象返回给调用者
                    return true;
                }

                // 同步请求发送：阻塞等待直到收到响应或超时
                bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, BaseMessage::ptr &rsp) {
                    AsynResponse rsp_future;
                    bool ret = send(conn, req, rsp_future);    // 复用异步发送接口
                    if(ret == false){
                        return false;
                    }
                    rsp = rsp_future.get();                    // 阻塞等待响应结果
                    return true;
                }

                // 回调式请求发送：提供回调函数处理响应，立即返回不阻塞
                bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, const RequestCallback &cb) {
                    RequestDescribe::ptr rdp = newDescribe(req, RType::REQ_CALLBACK, cb);
                    if(rdp.get() == nullptr){
                        ELOG("构造请求描述对象失败!");
                        return false;
                    }
                    conn->send(req);    // 发送请求后立即返回，响应将触发回调
                    return true;
                }

            private:
                // 创建新的请求描述对象并加入管理
                RequestDescribe::ptr newDescribe(const BaseMessage::ptr &req, RType rtype,
                    const RequestCallback &cb = RequestCallback()){
                        std::unique_lock<std::mutex> lock(_mutex);
                        RequestDescribe::ptr rd = std::make_shared<RequestDescribe>();  // 创建请求描述对象
                        rd->request = req;
                        rd->rtype = rtype;
                        if(rtype == RType::REQ_CALLBACK && cb){                        // 设置回调函数（如果是回调模式）
                            rd->callback = cb;              
                        }
                        _request_desc.insert(std::make_pair(req->rid(), rd));         // 将请求ID与描述对象关联存储
                        return rd;
                    }
                
                // 根据请求ID查找对应的请求描述
                RequestDescribe::ptr getDescribe(const std::string &rid){
                    std::unique_lock<std::mutex> lock(_mutex);
                    auto it = _request_desc.find(rid);
                    if(it == _request_desc.end()){
                        return RequestDescribe::ptr();          // 未找到则返回空指针
                    }
                    return it->second;                          // 返回找到的请求描述
                }
                
                // 删除已处理完成的请求描述，释放资源
                void delDescribe(const std::string &rid){
                    std::unique_lock<std::mutex> lock(_mutex);
                    _request_desc.erase(rid);                   // 从映射表中移除
                }

            private:
                std::mutex _mutex;                                                      // 保护请求映射表的互斥锁
                std::unordered_map<std::string, RequestDescribe::ptr> _request_desc;    // 请求ID到请求描述的映射表
        };
    }
}
